TOOL.Category    = "Conna's Tools"
TOOL.Name        = "#Fan Tool"
TOOL.Command     = nil
TOOL.ConfigName  = ""

TOOL.ClientConVar["Model"] = "models/props/de_prodigy/fanoff.mdl"
TOOL.ClientConVar["Description"] = ""
TOOL.ClientConVar["Length"] = "100"
TOOL.ClientConVar["Force"] = "1000"
TOOL.ClientConVar["Key"] = "5"
TOOL.ClientConVar["Toggle"] = "0"
TOOL.ClientConVar["Push"] = "0"
TOOL.ClientConVar["Sound"] = "1"
TOOL.ClientConVar["Effect"] = "1"

// Register

cleanup.Register("fans")

// Console

CreateConVar("sbox_maxfans", 10, FCVAR_NOTIFY)

// Client

if (CLIENT) then
	// Tool
	
	language.Add("Tool_fan_name", "Fan Tool")
	language.Add("Tool_fan_desc", "Fan which blows things infront of it backwards")
	language.Add("Tool_fan_0", "Left click to spawn a Fan")
	
	// Other
	
	language.Add("Undone_fan", "Undone Fan")
	language.Add("SBoxLimit_fans", "You've hit the Fans limit!")
	language.Add("Cleanup_fans", "Fans")
	language.Add("Cleaned_fans", "Cleaned up all Fans")
end

// Message

function TOOL:Message(Text)
	if (SERVER) then
		self:GetOwner():SendLua("GAMEMODE:AddNotify('"..Text.."', NOTIFY_GENERIC, 10)")
		self:GetOwner():SendLua("surface.PlaySound('ambient/water/drip"..math.random(1, 4)..".wav')")
	end
end

// Left click

function TOOL:LeftClick(Trace)
	if(CLIENT) then
		return true
	end
	
	// Locals
	
	local Player = self:GetOwner()

	local Key = self:GetClientNumber("Key")
	local Len = self:GetClientNumber("Length")
	local Toggle = self:GetClientNumber("Toggle")
	local Description = self:GetClientInfo("Description")
	local Model = self:GetClientInfo("Model")
	local Force = self:GetClientNumber("Force")
	local Effect = self:GetClientNumber("Effect")
	local Push = (self:GetClientNumber("Push") == 1)
	local Sound = self:GetClientNumber("Sound")
	
	// Keep it nice and whole
	
	Len   = math.Clamp(Len, 0, 10000)
	Force = math.Clamp(Force, 0, 100000)
	
	if (Trace.Entity and Trace.Entity:IsValid() and Trace.Entity:GetClass() == "gmod_fan") then
		local Entity = Trace.Entity
		
		// Merge
		
		local Table = {
			Toggle = Toggle,
			Push = Push,
			Sound = Sound,
			Description = Description
		}
		
		table.Merge(Entity:GetTable(), Table)
		
		// Other
		
		Entity:GetTable():SetEntityEffect(Effect)
		Entity:GetTable():SetEntityForce(Force)
		Entity:GetTable():SetEntityLength(Len)
		Entity:GetTable():SetEntityLabel(Description)
		
		self:Message("Properties changed for Fan!")
		
		return true
	end
	
	local Ang = Trace.HitNormal:Angle()
	
	Ang.pitch = Ang.pitch + 90

	local Fan = CreateFan(Player, Ang, Trace.HitPos, Model, Push, Sound, Effect, Force, Toggle, Len, Key, Description)
	
	if not (Fan) then return false end
	
	local Minimum = Fan:OBBMins()
	
	Fan:SetPos(Trace.HitPos - Trace.HitNormal * Minimum.z)
	
	undo.Create("fan")
	
	if (Trace.Entity and not Trace.Entity:IsWorld()) then
		local Weld = constraint.Weld(Fan, Trace.Entity, 0, Trace.PhysicsBone, 0, true, true)
		
		undo.AddEntity(Weld)
		
		Player:AddCleanup("fans", Weld)
		
		Fan:GetPhysicsObject():EnableCollisions(false)
	end
	
	undo.AddEntity(Fan)
	
	undo.SetPlayer(Player)
	
	undo.Finish()
	
	Player:AddCount("fans", Fan)
	
	Player:AddCleanup("fans", Fan)
	
	self:Message("Fan has been created!")
	
	return true, Fan
end

// Make it

if (SERVER) then
	function CreateFan(Player, Ang, Pos, Model, Push, Sound, Effect, Force, Toggle, Len, Key, Description, Nocollide, Vel, Avel, Frozen)
		if (!Player:CheckLimit("fans")) then return false end
		
		local Fan = ents.Create("gmod_fan")
		
		util.PrecacheModel(Model)
		
		Fan:SetModel(Model)
		Fan:SetAngles(Ang)
		Fan:SetPos(Pos)
		Fan:Spawn()
		
		// Merge
		
		local Table = {
			Toggle = Toggle,
			Push = Push,
			Sound = Sound,
			Description = Description
		}
		
		table.Merge(Fan:GetTable(), Table)
		
		// Set the entities owner
		
		Fan:GetTable():SetPlayer(Player)
		
		// Other
		
		Fan:GetTable():SetEntityEffect(Effect)
		Fan:GetTable():SetEntityForce(Force)
		Fan:GetTable():SetEntityLength(Len)
		Fan:GetTable():SetEntityKey(Key)
		Fan:GetTable():SetEntityLabel(Description)
		
		// Numpad
		
		numpad.OnDown(Player, Key, "Fan.Pressed", Fan, true)
		numpad.OnUp(Player, Key, "Fan.Pressed", Fan, false)
		
		if Frozen then Fan:GetPhysicsObject():EnableMotion(false) end
		
		if Nocollide then Fan:GetPhysicsObject():EnableCollisions(false) end
		
		return Fan
	end
	
	duplicator.RegisterEntityClass("gmod_fan", CreateFan, "Ang", "Pos", "Model", "Push", "Sound", "Effect", "Force", "Toggle", "Len", "Key", "Description", "Nocollide", "Vel", "Avel", "Frozen")
end

// Control panel

function TOOL.BuildCPanel(Panel)
	Panel:AddControl("Header", {Text = "#Tool_fan_name", Description = "#Tool_fan_desc"})

	local Models = {}
	
	Models["Spinner"] = {}
	Models["Spinner"]["fan_Model"] = "models/props/de_prodigy/fanoff.mdl"
	
	Panel:AddControl("ComboBox", {Label = "Model", Options = Models, MenuButton = 0})
	
	Panel:AddControl("Slider", {Label = "Length", Type = "Integer", Min = 0, Max = 10000, Command = "fan_Length"})
	
	Panel:AddControl("Slider", {Label = "Force", Type = "Integer", Min = 0, Max = 100000, Command = "fan_Force"})
	
	Panel:AddControl("Numpad", {Label = "Key", Command = "fan_Key", ButtonSize = 22})
	
	Panel:AddControl("CheckBox", {Label = "Toggle", Command = "fan_Toggle"})
	
	Panel:AddControl("CheckBox", {Label = "Push away from entities", Command = "fan_Push"})
	
	Panel:AddControl("CheckBox", {Label = "Sound", Command = "fan_Sound"})
	
	Panel:AddControl("CheckBox", {Label = "Effect", Command = "fan_Effect"})

	Panel:AddControl("TextBox", {Label = "Description", MaxLength = "100", Command = "fan_Description"})
end

// Ghost

function TOOL:UpdateGhostFan(Entity, Player)
	if (!Entity) then return end
	
	if (!Entity:IsValid()) then return end

	local TR = utilx.GetPlayerTrace(Player, Player:GetCursorAimVector())
	
	local Trace = util.TraceLine(TR)
	
	if (!Trace.Hit) then return end
	
	if (Trace.Entity && Trace.Entity:GetClass() == "gmod_fan" || Trace.Entity:IsPlayer()) then
		Entity:SetNoDraw(true)
		
		return
	end
	
	local Ang = Trace.HitNormal:Angle()
	
	Ang.pitch = Ang.pitch + 90
	
	local Minimum = Entity:OBBMins()
	
	Entity:SetPos(Trace.HitPos - Trace.HitNormal * Minimum.z)
	
	Entity:SetAngles(Ang)
	
	Entity:SetNoDraw(false)
end

// Think

function TOOL:Think()
	if not (self.Precached) then
		util.PrecacheModel("models/props/de_prodigy/fanoff.mdl")
		
		self.Precached = true
	end
	
	if (self:GetOwner() and self:GetOwner():IsPlayer()) then
		if (!self.GhostEntity || !self.GhostEntity:IsValid() || self.GhostEntity:GetModel() != self:GetClientInfo("Model")) then
			self:MakeGhostEntity(self:GetClientInfo("Model"), Vector(0, 0, 0), Angle(0, 0, 0) )
		end
		
		self:UpdateGhostFan(self.GhostEntity, self:GetOwner())
	end
end